package com.zhixue.media.jobhandler;


import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.zhixue.media.po.MediaProcess;
import com.zhixue.media.service.*;
import com.zhixue.utils.Mp4VideoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.List;
import java.util.concurrent.*;

//视频处理任务类
@Component
@Slf4j
public class VideoJob {

    @Autowired
    private MediaProcessService processService;

    @Autowired
    private MediaFilesService mediaFilesService;

    @Value("${videoprocess.ffmpegpath}")
    private String ffmpegPath;

    @XxlJob("VideoJobHandler")
    public void VideoJobHandler() throws Exception {
        // 分片参数
        //执行器的序号
        int shardIndex = XxlJobHelper.getShardIndex();
        //执行器总数
        int shardTotal = XxlJobHelper.getShardTotal();
        //获取cpu核数
        int count = Runtime.getRuntime().availableProcessors();
        //1.查询待处理任务
        List<MediaProcess> mediaProcessList = processService.getMediaProcessList(shardIndex, shardTotal, count - 2);
        if (mediaProcessList != null && !mediaProcessList.isEmpty()) {
            //创建线程池
            ExecutorService executorService = Executors.newFixedThreadPool(mediaProcessList.size());
            CountDownLatch countDownLatch = new CountDownLatch(mediaProcessList.size());
            mediaProcessList.forEach(mediaProcess -> {
                executorService.execute(() -> {
                    try {
                        //2.开启任务
                        int r = processService.startTask(mediaProcess.getId());
                        if (r <= 0) {
                            return;
                        }
                        //原avi视频的路径
                        String bucket = mediaProcess.getBucket();
                        String filePath = mediaProcess.getFilePath();
                        File file = mediaFilesService.downloadFileFromMinIO(bucket, filePath);
                        if (file == null) {
                            //保存失败结果
                            processService.saveProcessFinishStatus(mediaProcess.getId(), "3", mediaProcess.getFileId(), null, "下载文件异常");
                            return;
                        }
                        String videoPath = file.getAbsolutePath();
                        //转换后mp4的名称
                        String mp4Name = mediaProcess.getFileId() + ".mp4";
                        //转换后mp4的路径
                        File minio = null;
                        try {
                            minio = File.createTempFile("mp4", ".mp4");
                        } catch (IOException e) {
                            //保存失败结果
                            processService.saveProcessFinishStatus(mediaProcess.getId(), "3", mediaProcess.getFileId(), null, "创建临时文件异常");
                            throw new RuntimeException(e);
                        }
                        String mp4Path = minio.getAbsolutePath();
                        //3.执行转码任务
                        Mp4VideoUtil mp4VideoUtil = new Mp4VideoUtil(ffmpegPath, videoPath, mp4Name, mp4Path);
                        String result = mp4VideoUtil.generateMp4();
                        if (!"success".equals(result)) {
                            processService.saveProcessFinishStatus(mediaProcess.getId(), "3", mediaProcess.getFileId(), null, "视频转码失败");
                            return;
                        }
                        String objectName = getFileByMd5(mediaProcess.getFileId(), ".mp4");
                        String url = "/" + bucket + "/" + objectName;
                        //4.上传到minio
                        boolean b = mediaFilesService.upLoadToMinio(bucket, mp4Path, objectName, "video/mp4");
                        if (!b) {
                            processService.saveProcessFinishStatus(mediaProcess.getId(), "3", mediaProcess.getFileId(), null, "上传minio失败");
                            return;
                        }
                        //5.保存任务的处理结果
                        processService.saveProcessFinishStatus(mediaProcess.getId(), "2", mediaProcess.getFileId(), url, null);
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            });
            countDownLatch.await(10, TimeUnit.MINUTES);
        }
    }

    private String getFileByMd5(String fileMd5, String fileExt) {
        return fileMd5.substring(0, 1) + "/" + fileMd5.substring(1, 2) + "/" + fileMd5 + "/" + fileMd5 + fileExt;
    }
}
